package com.imooc.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.Frame;

import java.io.File;

/**
 * @Description
 * @Author 梦魂
 * @Date 2025/9/4 15:08
 */
@Slf4j
public class VideoUtil {


    public void compress(MultipartFile videoFile){
        long originalFileSize = 0;
        long compressedFileSize = 0;
        try {
            String projectRoot = System.getProperty("user.dir");
            File tempDir = new File(projectRoot, "temp");
            if (!tempDir.exists()) {
                tempDir.mkdirs();
            }
            // 先将原始文件保存到临时文件
            String originalFilename = videoFile.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            File tempOriginalFile = File.createTempFile("original-", fileExtension,tempDir);
            videoFile.transferTo(tempOriginalFile);

            // 获取原始文件大小
            originalFileSize = tempOriginalFile.length();
            System.out.println("原始视频文件大小: "+originalFileSize+" bytes ("+String.format("%.2f", originalFileSize / (1024.0 * 1024.0))+" MB)");

            // 压缩视频文件
            File tempCompressedFile = File.createTempFile("compressed-", fileExtension,tempDir);
            compressVideoFile(tempOriginalFile, tempCompressedFile);
        }catch (Exception e) {
            System.out.println("处理视频失败");
            throw new RuntimeException("处理视频失败", e);
        }
    }


    /**
     * 压缩视频文件
     * @param inputFile 输入文件
     * @param outputFile 输出文件
     */
    private void compressVideoFile(File inputFile, File outputFile) {
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;

        try {
            grabber = new FFmpegFrameGrabber(inputFile.getAbsolutePath());
            grabber.start();

            long inputFileSize = inputFile.length();
            double fileSizeMB = inputFileSize / (1024.0 * 1024.0);

            // 根据文件大小选择不同的压缩策略
            int targetWidth, targetHeight, targetBitrate, targetFps;
            String preset;

            if (fileSizeMB < 10) {
                // 小文件 - 轻度压缩
                targetWidth = Math.min(grabber.getImageWidth(), 640);
                targetHeight = Math.min(grabber.getImageHeight(), 360);
                targetBitrate = 800000;
                targetFps = (int) Math.min(grabber.getFrameRate(), 20);
                preset = "veryfast";
            } else if (fileSizeMB < 50) {
                // 中等文件 - 中度压缩
                targetWidth = Math.min(grabber.getImageWidth(), 480);
                targetHeight = Math.min(grabber.getImageHeight(), 270);
                targetBitrate = 500000;
                targetFps = (int) Math.min(grabber.getFrameRate(), 15);
                preset = "superfast";
            } else {
                // 大文件 - 重度压缩
                targetWidth = Math.min(grabber.getImageWidth(), 320);
                targetHeight = Math.min(grabber.getImageHeight(), 180);
                targetBitrate = 300000;
                targetFps = (int) Math.min(grabber.getFrameRate(), 10);
                preset = "ultrafast";
            }

            recorder = new FFmpegFrameRecorder(outputFile.getAbsolutePath(),
                    targetWidth, targetHeight, Math.min(grabber.getAudioChannels(), 1));

            // 设置基本参数
            recorder.setFormat("mp4");
            recorder.setVideoCodec(org.bytedeco.ffmpeg.global.avcodec.AV_CODEC_ID_H264);
            recorder.setFrameRate(targetFps);
            recorder.setVideoBitrate(targetBitrate);

            // 编码优化
            recorder.setOption("preset", preset);
            recorder.setOption("crf", "26");
            recorder.setOption("threads", "0");

            // 设置像素格式
            recorder.setPixelFormat(org.bytedeco.ffmpeg.global.avutil.AV_PIX_FMT_YUV420P);

            recorder.start();

            Frame frame;
            while ((frame = grabber.grab()) != null) {
                recorder.record(frame);
            }

        } catch (Exception e) {
            log.error("视频压缩处理失败", e);
            throw new RuntimeException("视频压缩处理失败", e);
        } finally {
            // 确保资源正确释放
            if (recorder != null) {
                try {
                    recorder.stop();
                    recorder.release();
                } catch (Exception e) {
                    log.error("释放recorder资源失败", e);
                }
            }
            if (grabber != null) {
                try {
                    grabber.stop();
                    grabber.release();
                } catch (Exception e) {
                    log.error("释放grabber资源失败", e);
                }
            }
        }
    }
}
